//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <string.h>
#include <stdio.h>
#include <aura.h>

Aura_Handle g_hCondition;
Aura_Handle g_hMutex;

void waitthread(Aura_PVoid pArg)
{
    Aura_ECode ec;
    Aura_WaitResult wResult;
    Aura_ThreadId Aura_ThreadId;
    Aura_Millisecond timeout = (Aura_Millisecond)pArg;
    int i = 0;

    AuraThread_GetCurrentId(&Aura_ThreadId);

    while(1){
        i++;

        ec = AuraMutex_Lock(g_hMutex, AURA_INFINITE, &wResult);
        if(AURA_FAILED(ec)){
            printf("Lock failed!\n");
            return;
        }

        if(0 == i%5){
            printf("Aura_ThreadId:%d, will enter wait time infinite\n", Aura_ThreadId);
            timeout = AURA_INFINITE;
        } else {
            timeout = (Aura_Millisecond)pArg;
            printf("Aura_ThreadId:%d, will enter wait time %d.\n", Aura_ThreadId, timeout);
        }

        ec = AuraCondition_Wait(g_hCondition, g_hMutex, timeout, &wResult);
        if(AURA_FAILED(ec)){
            printf("AuraCondition_Wait failed!\n");
            AuraMutex_Unlock(g_hMutex);
            return;
        }

        if(Aura_WaitResult_TimedOut == wResult){
            printf("Aura_ThreadId:%d, wait time out\n", Aura_ThreadId);
        } else if(Aura_WaitResult_OK == wResult){
            printf("Aura_ThreadId:%d, Get pulse!\n", Aura_ThreadId);
        } else {
            printf("Aura_ThreadId:%d, Out wait!!!!\n", Aura_ThreadId);
        }

        ec = AuraMutex_Unlock(g_hMutex);
        if(AURA_FAILED(ec)){
            printf("Unlock failed!\n");
            return;
        }

    }

}

#define MAXTHREAD 5

int main(int argc, char *argv[])
{
    Aura_ECode ec;
    Aura_Handle hThread[MAXTHREAD];
    int i;
    Aura_WaitResult wResult;

    memset(hThread, 0, MAXTHREAD*sizeof(Aura_Handle));

    ec = AuraMutex_Create(NULL, AURA_FALSE, &g_hMutex);
    if(AURA_FAILED(ec)){
        return ec;
    }

    ec = AuraCondition_Create(&g_hCondition);
    if(AURA_FAILED(ec)){
        return ec;
    }

    for(i = 0; i < MAXTHREAD; i++){
        ec = AuraThread_Create(waitthread,
                          (Aura_PVoid)(1000 + i*1000),
                          0,
                          &hThread[i],
                          NULL);
        if(AURA_FAILED(ec)){
            goto EXIT;
        }
    }

    printf("Test condition pulse All.\n");
    while('q' != getchar()){

        ec = AuraMutex_Lock(g_hMutex, AURA_INFINITE, &wResult);
        if(AURA_FAILED(ec)){
            printf("Main Lock failed!\n");
            goto EXIT;
        }
        printf("***********Pulse All***********\n");
        AuraCondition_PulseAll(g_hCondition);

        ec = AuraMutex_Unlock(g_hMutex);
        if(AURA_FAILED(ec)){
            printf("Main Unlock failed!\n");
            goto EXIT;
        }

    }

    printf("Test condition pulse.\n");
    while('q' != getchar()){

        ec = AuraMutex_Lock(g_hMutex, AURA_INFINITE, &wResult);
        if(AURA_FAILED(ec)){
            printf("Main Lock failed!\n");
            goto EXIT;
        }
        printf("***********Pulse***********\n");
        AuraCondition_Pulse(g_hCondition);

        ec = AuraMutex_Unlock(g_hMutex);
        if(AURA_FAILED(ec)){
            printf("Main Unlock failed!\n");
            goto EXIT;
        }

    }




EXIT:
    for(i = 0; i < MAXTHREAD; i++){
        if(NULL != hThread[i]){
            AuraThread_Abort(hThread[i], 0);
            AuraThread_Destroy(hThread[i]);
        }
    }
    AuraMutex_Destroy(g_hMutex);
    AuraCondition_Destroy(g_hCondition);
    return 0;
}

